//
//$Id: sets.h 687 2011-03-13 12:21:29Z andrew.tsyganov $
#pragma once

#include <algorithm>
#include <set>
#include "types.h"

#ifdef _MSC_VER
#pragma warning (push, 0)
#endif

#include "contrib/bm/src/bm.h"
#include "contrib/bm/src/bmserial.h"

#ifdef _MSC_VER
#pragma warning (pop)
#endif

//const unsigned kBitSetMaxSize = 0x0000FFFF;
const unsigned kBitSetMaxSize = 0xFFFFFFFF;

class IntSet;
class BitSet;
class FA;

typedef bm::bvector<> bvector;
typedef std::set<u_t> uset;

class BitSet_Serializer: public bm::serializer<bvector>
{
public:
    BitSet_Serializer()
    { 
        byte_order_serialization(false);
        gap_length_serialization(false);
        set_compression_level(4);
    }
};

class BitSet: public bm::bvector<>
{
public:
    //BitSet(): bm::bvector<>(bm::BM_GAP) {};
	BitSet(): bvector(bm::BM_GAP, bm::gap_len_table_min<true>::_len, kBitSetMaxSize) {}
    
    inline void insert(u_t const id) { set((bm::id_t)id); }
    inline void remove(u_t const id) { set((bm::id_t)id, false); }
    inline void remove() { reset(); }

    inline bool contains(u_t const id) const { return test((bm::id_t)id); }
    inline bool empty()  const { return none(); }
    inline size_t size() const { return count(); }

#if defined(_MSC_VER)
    //:warning 4267 supressors
    inline reference operator[](u_t n) { return bvector::operator[]((bm::id_t)n); }
    inline bool      operator[](u_t n) const { return bvector::operator[]((bm::id_t)n); }
    inline u_t get_next(u_t prev) const { return bvector::get_next((bm::id_t)prev); }
    inline void insert_range(u_t left, u_t right, bool value = true) { bvector::set_range((bm::id_t)left, (bm::id_t)right, value); }
#endif

    u_t get_By_Count(u_t const i) const; // slow

    unsigned char* serialize(BitSet_Serializer& ss, unsigned& len) const;
    void deserialize(unsigned char const* buf) { reset(); bm::deserialize(*this, buf); }

	IntSet to_IntSet() const;

    std::string to_String(Brackets_Type const bt = BRACES, int const add = 0) const;
    std::string to_String(std::string const& pfx, Brackets_Type const bt = BRACES, Labels_Type const lt = TXT, int const add = 0) const;

    u_t calc_Hash() const;
};

BitSet operator |(BitSet const& lhs, BitSet const& rhs);
BitSet operator &(BitSet const& lhs, BitSet const& rhs);
BitSet operator -(BitSet const& lhs, BitSet const& rhs);

bool operator <=(BitSet const& lhs, BitSet const& rhs);


class IntSet: public uset
{
public:
	inline void remove(u_t const id) { erase(id); }
	inline void remove() { clear(); }
	inline bool contains(u_t const id) const { return find(id) != end(); }
	void insert_range(u_t left, u_t right, bool value = true); 

	u_t get_By_Count(u_t const i) const; 

    void operator |=(IntSet const& is);
    void operator &=(IntSet const& is);
    void operator -=(IntSet const& is);

	void serialize(unsigned char* buf, unsigned& len) const;
    unsigned char* serialize(unsigned& len) const;
    void deserialize(unsigned char const* buf);

	BitSet to_BitSet() const;

	std::string to_String(Brackets_Type const bt = BRACES, int const add = 0) const;
    std::string to_String(std::string const& pfx, Brackets_Type const bt = BRACES, Labels_Type const lt = TXT, int const add = 0) const;

    u_t calc_Hash() const;
};

bool operator ==(IntSet const& lhs, IntSet const& rhs);
bool operator <=(IntSet const& lhs, IntSet const& rhs);


u_t FindEmptySet(std::vector<Subset> const& vs);
u_t FindEmptySet(std::vector<Subset> const& vs1, std::vector<Subset> const& vs2);

bool FindInVector(std::vector<BitSet> const& vbs, BitSet const& s, u_t& id);
void PrintVector(std::ostream& os, std::vector<BitSet> const& vbs);

//EOF!
